package com.xin.spring.framework.xml.factory;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 工厂类
 */
public class BeanFactory {

    private static Map<String, Object> iocMap = new ConcurrentHashMap<>();

    static {
        //step 1 加载xml
        InputStream is = BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml");
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read(is);
            Element rootElement = document.getRootElement();


            /**
             * XPath 路径表达式获取XML的节点
             *
             * nodename  获取此节点所有子节点
             * /         从根节点选取
             * //        从匹配选择的当前节点选择文档中的节点，不考虑位置
             * .         选取当前节点
             * ..        选取当前节点的父节点
             * @         选取属性
             */
            List<Element> elementList = rootElement.selectNodes("//bean");
            for (int i = 0; i < elementList.size(); i++) {
                Element element = elementList.get(i);
                String id = element.attributeValue("id");
                String className = element.attributeValue("class");
                Class<?> clazz = Class.forName(className);
                Object o = clazz.newInstance();
                iocMap.put(id, o);
            }

            //维护对象依赖
            List<Element> propertyList = rootElement.selectNodes("//property");
            for (int i = 0; i < propertyList.size(); i++) {
                Element element = propertyList.get(i);
                String name = element.attributeValue("name");
                String ref = element.attributeValue("ref");

                Element parent = element.getParent();
                Object obj = iocMap.get(parent.attributeValue("id"));
                Method[] methods = obj.getClass().getMethods();
                for (int j=0; j<methods.length; j++){
                    Method method = methods[j];
                    if(method.getName().equalsIgnoreCase("set"+ name)){
                        method.invoke(parent, iocMap.get(ref));
                    }
                }
                iocMap.put(parent.attributeValue("id"), parent);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * step2 根据ID获取Bean
     *
     * @param id ID
     * @return 结果
     */
    public static Object getBean(String id) {
        return iocMap.get(id);
    }
}
